﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using LFSRecord2.Events;
using LFSRecord2.Model;
using LFSRecord2.Model.UserActions;

namespace LFSRecord2.View.TimelineStructures
{
    /// <summary>
    /// Interaction logic for ParentLayerSelectionControl.xaml
    /// </summary>
    public partial class ParentLayerSelectionControl : Grid
    {
        int NumLayers;
        LayerInfoObject[] LayersInfo;

        public static DependencyProperty HasParentLayerProperty = DependencyProperty.Register(
          "HasParentLayer",
          typeof(bool),
          typeof(ParentLayerSelectionControl),
          new FrameworkPropertyMetadata(new PropertyChangedCallback(HasParentLayerChanged))
        );
        public bool HasParentLayer
        {
            get { return (bool)GetValue(HasParentLayerProperty); }
            set { SetValue(HasParentLayerProperty, value); }
        }
        private static void HasParentLayerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((ParentLayerSelectionControl)d).WriteLabel();
        }

        public ParentLayerSelectionControl()
        {
            InitializeComponent();
        }

        private void Grid_Loaded(object sender, RoutedEventArgs e)
        {
            Binding myBinding = new Binding("HasParentLayer");
            myBinding.Mode = BindingMode.OneWay;
            myBinding.Source = (CompLayerBase)DataContext;
            SetBinding(ParentLayerSelectionControl.HasParentLayerProperty, myBinding);

            WriteLabel();
        }

        private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;

            //Debug.WriteLine("binding icon clicked");
            NumLayers = LfsRecordController.project.Layers.Count;
            LayersInfo = new LayerInfoObject[NumLayers];

            // Populate layersInfo
            for (int a = 0; a < NumLayers; a++)
            {
                LayersInfo[a] = new LayerInfoObject(
                    a, 
                    ((LfsRecordController.project.Layers[a].HasParentLayer) ? LfsRecordController.project.Layers[a].ParentLayer.LayerIndex : -1), 
                    LfsRecordController.project.Layers[a].LayerType, 
                    LfsRecordController.project.Layers[a].LayerName, 
                    LfsRecordController.project.Layers[a].Properties.Count,
                    -1);
            }

            // Build and show selection context menu
            ContextMenu = null;
            ShowContextMenu();
            LayersInfo = null;
        }

        private void Grid_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
        }

        private void WriteLabel()
        {
            CompLayerBase layerSelf = (CompLayerBase)DataContext;
            if (layerSelf.HasParentLayer)
            {
                ParentNameLabel.Content = layerSelf.ParentLayer.LayerName;
            }
            else
            {
                ParentNameLabel.Content = "Parent (none)";
            }
        }

        private void ShowContextMenu()
        {
            CompLayerBase layerSelf = (CompLayerBase)DataContext;

            // Create context menu
            MenuItem mi;
            Separator sep = new Separator();
            //Binding myBinding;
            ContextMenu cm = new ContextMenu();

            for (int a = 0; a < NumLayers; a++)
            {
                if (LfsRecordController.project.Layers[a].LayerType == CompLayerTypes.ReplayControl)
                    continue;

                mi = new MenuItem();
                mi.Header = LayersInfo[a].LayerName;

                if (a == layerSelf.LayerIndex || LayersInfo[a].ParentIndex == layerSelf.LayerIndex)
                {
                    mi.IsEnabled = false;
                }
                mi.Command = ValueBinding_ClickedCommand;
                mi.CommandParameter = new LayerPropIndex { LayerIndex = (short)a, PropertyIndex = (sbyte)-1 };

                cm.Items.Add(mi);
            }

            cm.Items.Add(sep);

            mi = new MenuItem();
            mi.Header = "No parent";
            mi.Command = ValueBinding_ClickedCommand;
            mi.CommandParameter = null;
            cm.Items.Add(mi);

            ContextMenu = cm;
            ContextMenu.Unloaded += new RoutedEventHandler(ContextMenu_Unloaded);
            ContextMenu.IsOpen = true;
        }

        // ValueBinding_ClickedCommand
        RelayCommand _valueBinding_ClickedCommand;
        public ICommand ValueBinding_ClickedCommand
        {
            get
            {
                if (_valueBinding_ClickedCommand == null)
                    _valueBinding_ClickedCommand = new RelayCommand(param => this.ValueBinding_ClickedCommandExecute(param), param => ValueBinding_ClickedCommandCanExecute(param));
                return _valueBinding_ClickedCommand;
            }
        }
        void ValueBinding_ClickedCommandExecute(object param)
        {
            // Set the selected parent
            CompLayerBase layerSelf = (CompLayerBase)DataContext;
            int oldParentLayerIndex = (layerSelf.ParentLayer == null) ? -1 : layerSelf.ParentLayer.LayerIndex;

            if (param == null)
            {
                // Remove
                //Debug.WriteLine("We have to remove the binding at property {0} on layer {1}", propSelf.BindingPropertyIndex.PropertyIndex, propSelf.BindingPropertyIndex.LayerIndex);
                layerSelf.ParentLayer = null;
                layerSelf.SetCurrentTransformMatrix();
                WriteLabel();
            }
            else
            {
                // Set
                layerSelf.ParentLayer = LfsRecordController.project.Layers[((LayerPropIndex)param).LayerIndex];
                layerSelf.SetCurrentTransformMatrix();
                WriteLabel();
            }

            int newParentLayerIndex = (layerSelf.ParentLayer == null) ? -1 : layerSelf.ParentLayer.LayerIndex;
            if (oldParentLayerIndex != newParentLayerIndex)
            {
                LfsRecordController.RecordUserAction(new UserActionLayerParentChanged()
                {
                    LayerIndex = layerSelf.LayerIndex,
                    OldParentLayerIndex = oldParentLayerIndex,
                    NewParentLayerIndex = newParentLayerIndex
                });
            }
            LfsRecordController.CreateUndoLevel();
            ServicesFactory.EventService.GetEvent<CompLayerPropertyChangedEvent>().Publish(new CompLayerPropertyChangedEventArgs { Sender = this, PropertyType = "Value", UpdateCurrentValues = true });
        }
        bool ValueBinding_ClickedCommandCanExecute(object param)
        {
            CompLayerBase layerSelf = (CompLayerBase)DataContext;
            if (param == null)
            {
                return layerSelf.HasParentLayer;
            }
            return true;
        }

        void ContextMenu_Unloaded(object sender, RoutedEventArgs e)
        {
            //Debug.WriteLine("Context menu gone");
            ContextMenu = null;
        }
    }
}
